package com.handu.luna.core.domain.system;


import com.handu.luna.core.domain.BasePersistentDomain;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.jpa.repository.JpaRepository;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by wangzailiang on 2014/7/15.
 */
@Entity
public class DeliverArea extends BasePersistentDomain<DeliverAreaRepository> {

    public static final String DELIMITER = ",";

    @NotNull(message = "请输入配送区域名称")
    @Size(max = 100,message = "最大不能超过100个字符")
    private String name;
    @NotNull(message = "请输入配送区域描述")
    @Size(max = 254 , message = "最大不能超过255个字符")
    private String description;
    @NotNull(message = "请输入费用")
    private BigDecimal price;
    private String regionIds;
    private String filterRegionIds;
    private boolean filterable = false;
    @Transient private List<Long> regionIdList;
    @Transient private List<Long> filterRegionIdList;
    @Transient private List<Region> regionList;
    @Transient private List<Region> filterRegionList;
    @Transient private Map<String,Long> filterViews;

    @PostLoad
    public void init() {
        if(StringUtils.isNotBlank(regionIds)) {
            regionList = new ArrayList<Region>();
            for (String regionStrId : this.strToList(regionIds)) {
                long regionId = Long.parseLong(regionStrId);
                regionList.add(context.getRegionRepository().findOne(regionId));
            }
        }
        if(StringUtils.isNotBlank(filterRegionIds)) {
            filterRegionList = new ArrayList<>();
            filterViews = new LinkedHashMap<>();
            for (String filterRegionStrId : this.strToList(filterRegionIds)) {
                long regionId = Long.parseLong(filterRegionStrId);
                Region region = context.getRegionRepository().findOne(regionId);
                filterRegionList.add(region);
                if(region.getLevel() == 3) {
                    Region city = context.getRegionRepository().findOne(region.getParentId());
                    Region province = context.getRegionRepository().findOne(city.getParentId());
                    filterViews.put(province.getName() + "  " + city.getName() + "  " + region.getName(), regionId);
                }
                if(region.getLevel() == 2) {
                    Region province = context.getRegionRepository().findOne(region.getParentId());
                    filterViews.put(province.getName() + "  " + region.getName(), regionId);
                }
            }
        }
    }

    @PrePersist
    public void prePersist() {
        if(CollectionUtils.isNotEmpty(regionIdList)) {
            regionIds = this.listToStr(regionIdList);
        }
        if(CollectionUtils.isNotEmpty(filterRegionIdList)) {
            filterRegionIds = this.listToStr(filterRegionIdList);
        }
    }

    public void update() {
        prePersist();
        context.getDeliverAreaRepository().save(this);
    }

    public String listToStr(List<Long> list) {
        StringBuilder sb = new StringBuilder();
        for (Long id : list) {
            sb.append(String.valueOf(id)).append(DELIMITER);
        }
        return sb.toString();
    }

    public List<String> strToList(String arrayString) {
        List<String> list = new ArrayList<String>();
        for(String item : arrayString.split(DELIMITER)) {
            list.add(item);
        }
        return list;
    }

    public List<Region> filterRegions() {
        List<Region> regionList = context.getRegionRepository().findRegionListByParentId(1);
        if(null != this.getRegionList()) {
           regionList.removeAll(this.getRegionList());
        }
        return regionList;
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
    public void merge(String[] fields) {
        List<Long> tempRegionIdList = this.getRegionIdList();
        List<Long> tempFilterRegionIdList = this.getFilterRegionIdList();
        if (!this.isNew()) {
            Object thisDomainInDB = null;
            try {
                thisDomainInDB = BeanUtils.cloneBean(((JpaRepository) getRepository()).findOne(this.getId()));
            } catch (IllegalAccessException | InstantiationException
                    | InvocationTargetException | NoSuchMethodException e1) {
                logger.debug("error in copy merge a domain", e1);
            }
            for (String field : fields) {
                try {
                    String property = BeanUtils.getProperty(this, field);
                    if (field.endsWith("Date") || field.endsWith("beginTime") || field.endsWith("endTime")) {
                        Date date = new SimpleDateFormat("EE MMM dd HH:mm:ss 'CST' yyyy", java.util.Locale.US).parse(property);
                        BeanUtils.copyProperty(thisDomainInDB, field, date);
                    } else {
                        BeanUtils.copyProperty(thisDomainInDB, field, property);
                    }
                } catch (IllegalAccessException | InvocationTargetException
                        | NoSuchMethodException e) {
                    logger.debug("error in copy merge a domain", e);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            try {
                BeanUtils.copyProperties(this, thisDomainInDB);
            } catch (IllegalAccessException | InvocationTargetException e) {
                logger.debug("error in copy merge a domain", e);
            }
        }
        this.setRegionIdList(tempRegionIdList);
        this.setFilterRegionIdList(tempFilterRegionIdList);
    }

    public DeliverArea(){}

    public DeliverArea(String name, String description, BigDecimal price) {
        this.name = name;
        this.description = description;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

    public String getRegionIds() {
        return regionIds;
    }

    public void setRegionIds(String regionIds) {
        this.regionIds = regionIds;
    }

    public List<Region> getRegionList() {
        return regionList;
    }

    public void setRegionList(List<Region> regionList) {
        this.regionList = regionList;
    }

    public String getFilterRegionIds() {
        return filterRegionIds;
    }

    public void setFilterRegionIds(String filterRegionIds) {
        this.filterRegionIds = filterRegionIds;
    }

    public List<Region> getFilterRegionList() {
        return filterRegionList;
    }

    public void setFilterRegionList(List<Region> filterRegionList) {
        this.filterRegionList = filterRegionList;
    }

    public List<Long> getRegionIdList() {
        return regionIdList;
    }

    public void setRegionIdList(List<Long> regionIdList) {
        this.regionIdList = regionIdList;
    }

    public List<Long> getFilterRegionIdList() {
        return filterRegionIdList;
    }

    public void setFilterRegionIdList(List<Long> filterRegionIdList) {
        this.filterRegionIdList = filterRegionIdList;
    }

    public boolean isFilterable() {
        return filterable;
    }

    public void setFilterable(boolean filterable) {
        this.filterable = filterable;
    }

    public Map<String, Long> getFilterViews() {
        return filterViews;
    }

    public void setFilterViews(Map<String, Long> filterViews) {
        this.filterViews = filterViews;
    }


}
